/* model */
import Column from '@model/types/Column';
/* vue */
import Vue, { computed, ComputedRef, onBeforeMount, onBeforeUnmount, Ref, ref } from 'vue';
/* util */
import { 
  isTableCellInEdit, 
  setTableCellIsEditTrue, 
  setTableCellIsEditFalse, 
  isTableCellInEditNotUndefined
} from '@src/component/form/form-builder-table/util';
import { isFalsy } from '@src/util/type';

type ClickTableCellDataType = {
  row: Record<string, any> | null;
  column: Column | null;
  cell: Element | null;
  event: MouseEvent | null;
}

function useFormBuilderTableEdit(columns: Ref<Column[]>, instance: Vue<Record<string, any>> | undefined) {
  
  const { 
    onTableCellClickHandler, 
    effectClearHandler,
    lastClickTableCellData 
  } = useFormBuilderTableTableCellClick(columns);
  
  const { onDocumentClickHandler } = useFormBuilderTableDocumentClick(
    lastClickTableCellData, 
    effectClearHandler,
    instance
  );
  
  return {
    onTableCellClickHandler,
    onDocumentClickHandler,
    lastClickTableCellData
  }
  
}

/** 
 * @description 单元格点击事件
*/
function useFormBuilderTableTableCellClick(columns: Ref<Column[]>) {
  
  const columnFieldMap: ComputedRef<Record<string, Column>> = computed(() => {
    return (
      columns.value.reduce((previousValue, currentValue) => {
        previousValue[currentValue.field as string] = currentValue;
        return previousValue;
      }, {} as Record<string, Column>)
    )
  });
  
  /** 
   * @description 上一次点击的单元格数据
  */
  const lastClickTableCellData: Ref<ClickTableCellDataType> = ref({
    row: null,
    column: null,
    cell: null,
    event: null
  });
  
  /** 
   * @description 判断点击的单元格是否是同一个
  */
  function isClickSameCell(row: Record<string, any>, column: Column) {
    return lastClickTableCellData.value.row === row && lastClickTableCellData.value.column === column;
  }
  
  /**
   * @description 更新上一次点击的单元格数据
   */
  function updateLastClickTableCellData(row: Record<string, any>, column: Column, cell: Element, event: MouseEvent) {
    
    // 设置上一次点击的单元格为非编辑状态
    const { row: lastClickRow, column: lastClickColumn } = lastClickTableCellData.value;
    setTableCellIsEditFalse(lastClickRow!, lastClickColumn!)
    
    // 更新上一次点击的单元格数据
    lastClickTableCellData.value = {
      row,
      column,
      cell,
      event
    };
  }
  
  /** 
   * @description 单元格点击事件
  */
  function onTableCellClickHandler(row: Record<string, any>, elColumn: Record<string, any>, cell: Element, event: MouseEvent) {
    
    console.log('onTableCellClickHandler', event)
    
    // 因为在 document 上也注册了点击事件，所以阻止事件冒泡
    event?.stopPropagation();
    
    const column = columnFieldMap.value[elColumn?.property as string];
    // 判断是否是空列
    if (isFalsy(column)) {
      return;
    }
    
    // 判断是否是同一个单元格
    const isSameCell = isClickSameCell(row, column);
    if (isSameCell) {
      return;
    }
    
    // 更新上一次点击的单元格数据
    updateLastClickTableCellData(row, column, cell, event);
    
    
    const isEditNotUndefined = isTableCellInEditNotUndefined(row, column);
    // 判断是否是编辑状态或者是编辑状态未定义，如果是则不做任何操作
    const isEdit = isTableCellInEdit(row, column);
    if (isEdit && isEditNotUndefined) {
      return;
    }
    
    // 设置单元格为编辑状态
    setTableCellIsEditTrue(row, column);
    
  }
  
  function effectClearHandler() {
    lastClickTableCellData.value = {
      row: null,
      column: null,
      cell: null,
      event: null
    };
  }
  
  return {
    onTableCellClickHandler,
    effectClearHandler,
    lastClickTableCellData
  }
  
}

function useFormBuilderTableDocumentClick(
  lastClickTableCellData: Ref<ClickTableCellDataType>, 
  effectClearHandler: VoidFunction,
  instance: Vue<Record<string, any>> | undefined
) {
  
  function onDocumentClickHandler(event: Event) {
    
    console.log('onDocumentClickHandler', event)
    
    const target = event?.target as Element;
    
    const { row, column, cell } = lastClickTableCellData.value;
    // 判断是否有点击的单元格数据
    if (isFalsy(row) || isFalsy(column)) {
      console.warn('没有点击的单元格数据');
      return;
    }
    
    const blackElementClassNameList: string[] = [
      'bm-picker',
      'el-button',
      'el-message-box__wrapper'
    ];
    
    // 如果点击的是黑名单元素，不做处理
    const isBlackElement = blackElementClassNameList.some(className => target?.classList.contains(className));
    if (isBlackElement) {
      return;
    }
    
    // 如果点击的是黑名单元素的子元素，不做处理
    const isBlackChildrenElement = blackElementClassNameList.some(className => {
      const blackElement = document?.querySelector(`.${className}`);
      return blackElement?.contains(target as Node) || blackElement === target;
    });
    if (isBlackChildrenElement) {
      return;
    }
    
    const tableBodyElement = instance?.$el?.querySelector('.el-table__body-wrapper');
    const isInTableBodyElement = tableBodyElement?.contains(target as Node) || tableBodyElement === target;
    // 判断点击的单元格是否是当前表格内部的元素
    if (isInTableBodyElement) {
      console.warn('点击的单元格是当前表格内部的元素，不做处理');
      return;
    }
    
    const isInCellElement = cell?.contains(target as Node) || cell === target;
    // 判断点击的单元格是否是当前单元格
    if (isInCellElement) {
      console.warn('点击的单元格是当前单元格');
      return;
    }
    
    setTableCellIsEditFalse(row!, column!);
    
    effectClearHandler();
    
  }
  
  onBeforeMount(() => {
    document.addEventListener('click', onDocumentClickHandler);
  });
  
  onBeforeUnmount(() => {
    document.removeEventListener('click', onDocumentClickHandler);
  });
  
  return {
    onDocumentClickHandler
  }
}

export {
  useFormBuilderTableEdit
}
